// #include "rpcchannel.h"
// #include <string>
// #include "rpcheader.pb.h"
// #include "mprpcapplication.h"
// #include "arpa/inet.h"
// #include "sys/socket.h"
#include "rpcchannel.h"
#include <string>
#include "rpcheader.pb.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include "mprpcapplication.h"

void MprpcChannel::CallMethod(const google::protobuf::MethodDescriptor* method,
                            google::protobuf::RpcController* controller, 
                            const google::protobuf::Message* request,
                            google::protobuf::Message* response,
                            google::protobuf:: Closure* done) 
    {
        std::string method_name = method->name();
        std::string service_name =  method->service()->name();
        std::string args;
        uint32_t args_size = 0;
        if (request->SerializeToString(&args)) {
            args_size = args.size();
        } else {
            controller->SetFailed("serialize request error!");
            std::cout << "serialize request error!" << std::endl;
            return;
        }

        // 定义rpc的请求header
        mprpc::RpcHeader request_header;
        request_header.set_service_name(service_name);
        request_header.set_method_name(method_name);
        request_header.set_args_size(args_size);

        std::string rpc_header_str;
        uint32_t rpc_header_size = 0;
        if (request_header.SerializeToString(&rpc_header_str)) {
            rpc_header_size = rpc_header_str.size();
        } else {    
            controller->SetFailed("serrialize rpc header error!");
            std::cout << "serrialize rpc header error!" << std::endl;
            return;
        }

        std::string send_rpc_str;
        send_rpc_str.insert(0, std::string((char*)&rpc_header_size, 4));    // 代码过程中这里出现一个错误，这里的 4 ，写成了0，并且没有加上下面两行，导致send_rpc_str就是个空，发送过去后，server根本没有检测到有信息，onMessage回调函数就没有调用
        send_rpc_str += rpc_header_str; // rpcheader
        send_rpc_str += args; // args

        // 打印调试信息
        std::cout << "============================================" << std::endl;
        std::cout << "header_size: " << rpc_header_size << std::endl; 
        std::cout << "rpc_header_str: " << rpc_header_str << std::endl; 
        std::cout << "service_name: " << service_name << std::endl; 
        std::cout << "method_name: " << method_name << std::endl; 
        std::cout << "args_str: " << args << std::endl; 
        std::cout << "============================================" << std::endl;

        //  上面是参数序列化的部分，下面是发送的部分，分别对应图里的黄色和绿色


        // 使用tcp编程，完成rpc方法的远程调用
        int clientfd = socket(AF_INET, SOCK_STREAM, 0);
        if (-1 == clientfd)
        {
            char errtxt[512] = {0};
            sprintf(errtxt, "create socket error! errno:%d", errno);
            controller->SetFailed(errtxt);
            return;
        }

        // 读取配置文件rpcserver的信息
        // std::string ip = MprpcApplication::getInstance().getConfig().Load("rpcserverip");
        // uint16_t port = atoi(MprpcApplication::getInstance().getConfig().Load("rpcserverport").c_str());

        ZkClient zkCli;
        zkCli.Start();
        //  /UserServiceRpc/Login
        std::string method_path = "/" + service_name + "/" + method_name;
        // 127.0.0.1:8000
        std::string host_data = zkCli.GetData(method_path.c_str());
        if (host_data == "")
        {
            controller->SetFailed(method_path + " is not exist!");
            return;
        }
        int idx = host_data.find(":");
        if (idx == -1)
        {
            controller->SetFailed(method_path + " address is invalid!");
            return;
        }
        std::string ip = host_data.substr(0, idx);
        uint16_t port = atoi(host_data.substr(idx+1, host_data.size()-idx).c_str()); 

        struct sockaddr_in server_addr;
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(port);
        server_addr.sin_addr.s_addr = inet_addr(ip.c_str());

        // 连接rpc服务节点
        if (-1 == connect(clientfd, (struct sockaddr*)&server_addr, sizeof(server_addr)))
        {
            close(clientfd);
            char errtxt[512] = {0};
            sprintf(errtxt, "connect error! errno:%d", errno);
            controller->SetFailed(errtxt);
            return;
        }

        // 发送rpc请求
        if (-1 == send(clientfd, send_rpc_str.c_str(), send_rpc_str.size(), 0))
        {
            close(clientfd);
            char errtxt[512] = {0};
            sprintf(errtxt, "send error! errno:%d", errno);
            controller->SetFailed(errtxt);
            return;
        }

        // 接收rpc请求的响应值
        char recv_buf[1024] = {0};
        int recv_size = 0;
        if (-1 == (recv_size = recv(clientfd, recv_buf, 1024, 0)))
        {
            close(clientfd);
            char errtxt[512] = {0};
            sprintf(errtxt, "recv error! errno:%d", errno);
            controller->SetFailed(errtxt);
            return;
        }

        // 反序列化rpc调用的响应数据
        // std::string response_str(recv_buf, 0, recv_size); // bug出现问题，recv_buf中遇到\0后面的数据就存不下来了，导致反序列化失败，即response_str只是个"\n"
        // if (!response->ParseFromString(response_str))
        if (!response->ParseFromArray(recv_buf, recv_size))
        {
            close(clientfd);
            char errtxt[512] = {0};
            sprintf(errtxt, "parse error! response_str:%s", recv_buf);
            controller->SetFailed(errtxt);
            return;
        }

        close(clientfd);
}
                
